package self

import (
	"database/sql"
	"log"

	"github.com/kataras/iris"
	"github.com/lib/pq"
)

// GuardHelper self guard helper 守护助手
type GuardHelper struct {
	ctx iris.Context
	pg  *sql.DB
	log *log.Logger
}

// Watch create guard watch context
func newGuardHelper(ctx iris.Context, pg *sql.DB, log *log.Logger) *GuardHelper {
	return &GuardHelper{ctx: ctx, pg: pg, log: log}
}

// DefendPG defend postgreSQL handles
func (gh *GuardHelper) DefendPG(handle func(pg *sql.DB) error) bool {
	user, ok := gh.GetUser()
	if !ok {
		gh.ctx.StatusCode(iris.StatusUnauthorized)
		gh.ctx.Writef("没有验证信息")
		return false
	}

	rolename := "nouser"

	if role, ok := user["rolename"]; ok {
		rolename = role.(string)
	} else {
		gh.logf("rolename key not found")
	}

	_, err := gh.pg.Exec("SET ROLE " + rolename)
	if err != nil {
		pgErr, _ := err.(pq.Error)
		gh.logf("set role:code %s", pgErr.Code.Name())
		panic("set role error")
	}

	err = handle(gh.pg)

	gh.pg.Exec("RESET ROLE")

	if err != nil {
		if pgErr, ok := err.(pq.Error); ok {
			gh.logf("guard helper defend pg error code:%s", pgErr.Code.Name())
			return false
		}
		gh.logf("guard helper defend on url(%s) other error:%s", gh.ctx.RequestPath(false), err.Error())
		return false
	}
	return true
}

// GetUser 获取用户
func (gh *GuardHelper) GetUser() (map[string]interface{}, bool) {
	user := gh.ctx.Values().Get("self")
	if user == nil {

		gh.logf("user is not set")
		return nil, false
	}
	m, ok := user.(map[string]interface{})
	return m, ok
}

// NewGuardManager create new guard manager
func (gh *GuardHelper) NewGuardManager() *GuardManager {
	return newGuardManager(gh)
}

func (gh *GuardHelper) logf(format string, a ...interface{}) {
	if gh.log != nil {
		gh.log.Printf(format, a...)
	}
}
